#ifndef ROSTER_H
#define ROSTER_H

#include <QObject>
#include <QScriptable>
#include <QSet>
#include <QDebug>

class RosterElement;
class RosterUnit;
class RosterModel;
class ColumnHeader;
class UnitCollection;

class Roster : public QObject, protected QScriptable
{
    friend class RosterUnit;
    friend class RosterElement;
    Q_OBJECT
public:
    Roster(ColumnHeader *header);
    ~Roster();

    RosterModel* model();

    void addRosterElement(RosterElement *element, RosterElement *parent = 0);
    void removeRosterElement(int row);
    void clearAll();

    QSet<QString> getValidationErrors() const;

    int count();
    RosterElement* at(int i);
    RosterElement* value(int i);

public slots:
    void addError(const QString& error);
    void removeError(const QString& error);

signals:
    void pointsChanged(double newValue);
    void validationChanged(const QSet<QString> errors);

    void unitSizeChanged(RosterUnit *unit);
    void unitAdded(RosterUnit *unit);
    void unitAboutToBeRemoved(RosterUnit *unit);
    void unitCostChanged(RosterUnit *unit, float oldCost);
    void optionActivated(RosterUnit *unit, const QString& optionKey);
    void optionDeactivated(RosterUnit *unit, const QString& optionKey);
    void itemAdded(RosterUnit *unit, const QString& itemKey, quint8 number);
    void itemRemoved(RosterUnit *unit, const QString& itemKey, quint8 number);
    void itemLimitsChanged(RosterUnit *unit);

private:
    RosterElement *parentItem;
    RosterModel *rosterModel;

    double points;
    double maxPoints;

    QSet<QString> errors;

    void amountPoints(float points);

    // Used within RosterUnit/RosterElement
    void forceUpdate(RosterElement *element);
    void aboutToRemoveChildren(RosterElement *parent, int first, int end);
    void childrenRemoved();
    void aboutToAddChild(RosterElement *parent);
    void childAdded();

    // \TODO: Reevaluate this approach

    inline void emitUnitSizeChanged(RosterUnit *unit) {
        emit unitSizeChanged(unit);
    }

    inline void emitUnitAdded(RosterUnit *unit) {
        emit unitAdded(unit);
    }

    inline void emitUnitAboutToBeRemoved(RosterUnit *unit) {
        emit unitAboutToBeRemoved(unit);
    }

    inline void emitUnitCostChanged(RosterUnit *unit, float oldCost) {
        emit unitCostChanged(unit, oldCost);
    }

    inline void emitOptionActivated(RosterUnit *unit, const QString& optionKey) {
        emit optionActivated(unit, optionKey);
    }

    inline void emitOptionDeactivated(RosterUnit *unit, const QString& optionKey) {
        emit optionDeactivated(unit, optionKey);
    }

    inline void emitItemAdded(RosterUnit *unit, const QString& itemKey, quint8 number) {
        emit itemAdded(unit, itemKey, number);
    }

    inline void emitItemRemoved(RosterUnit *unit, const QString& itemKey, quint8 number) {
        emit itemRemoved(unit, itemKey, number);
    }

    inline void emitItemLimitsChanged(RosterUnit *unit) {
        emit itemLimitsChanged(unit);
    }
};

#endif // ROSTER_H
